<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="shortcut icon" href="../favicon.ico" />
    <link rel="bookmark" href="../favicon.ico" />
    <title>Document</title>
    <style>
       body {
        margin: 0;
        overflow: hidden;
      }
      #tip {
        position: absolute;
        top: 10px;
        left: 10px;
      }
    </style>
    <script src="./three.js"></script>
    <script src="./OrbitControls.js"></script>
    <script src="./Projector.js"></script>
  </head>
  <body>
    <div id="tip">键盘按下空格键后可以开始框选</div>
  </body>

  <script>
    var scene, camera, renderer, clock, controller;
    var meshes = [], canvas, ctx
    let projector = new THREE.Projector(); 
    init();
    animate();

    // - Functions -
    function init() {
      scene = new THREE.Scene();
      clock = new THREE.Clock();
      camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      camera.position.set(10, 10, 10)
      renderer = new THREE.WebGLRenderer({
        antialias: true, // 开启抗锯齿处理
        alpha: true,
      });
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setClearColor(0xffffff)

      var geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
      var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
      var material2 = material.clone()
      var material3 = material.clone()

      var cube = new THREE.Mesh( geometry, material );
      var cube2 = new THREE.Mesh( geometry, material2 );
      var cube3 = new THREE.Mesh( geometry, material3 );

      scene.add(cube)
      
     
      cube2.position.set(5, 0, 0)
      scene.add(cube2)

     
      cube3.position.set(0, 0, 5)
      scene.add(cube3)

      meshes = [cube, cube2, cube3]

      var axisHelper = new THREE.AxesHelper(10);
      scene.add(axisHelper);

      controller = new THREE.OrbitControls(camera, renderer.domElement);
      document.body.appendChild(renderer.domElement);

      addCanvas()

      window.onresize = onResize;

      document.onkeydown = function(e) {
        if(e.code == 'Space') {
          controller.enabled = false
          document.onmousedown = function(downEvent) {
            let startX = downEvent.clientX
            let startY = downEvent.clientY

            document.onmousemove = function(downmoveEvent) {
              let { clientX: moveX, clientY: moveY } = downmoveEvent
              drawCanvas(startX, startY, moveX, moveY)

              meshes.map(m => {
                if(isMeshInFrame(startX, startY, moveX, moveY, m)) {
                  m.material.color = new THREE.Color('#f00')
                }else {
                  m.material.color = new THREE.Color('#0f0')
                }
              })
            }

            document.onmouseup = function(upEvent) {
              let endX = upEvent.clientX
              let endY = upEvent.clientY
              clearCanvas()

              document.onmousemove = null
            }
          }
          
          document.onkeyup = function() {
            clearCanvas()
            document.onmousemove = null
            document.onmousedown = null
            document.onmouseup = null
            controller.enabled = true
          }
        }
      }
      
    }

    function addCanvas() {
      canvas = document.createElement('canvas')
      canvas.width = window.innerWidth
      canvas.height = window.innerHeight
      canvas.style.width = window.innerWidth + 'px'
      canvas.style.height = window.innerHeight + 'px'
      canvas.style.position = 'absolute'
      canvas.style.top = 0
      canvas.style.left = 0
      canvas.style.zIndex = 1
      canvas.style.pointerEvents = 'none'
      
      ctx = canvas.getContext('2d')
      document.body.appendChild(canvas)
    }

    function drawCanvas(startX, startY, endX, endY) {
      clearCanvas()
      ctx.strokeRect(startX, startY, endX - startX, endY - startY)

    }

    function clearCanvas() {
      ctx.clearRect(0, 0, window.innerWidth, window.innerHeight)
    }

    function isMeshInFrame(startX, startY, endX, endY, mesh) {
      // startX|startY ------ |
      // |                    |
      // |                    | 
      // | meshScreenPosition | 
      // |                    | 
      // |                    | 
      // |--------------- endX|endY 
      let meshScreenPosition = xyz2Screen(mesh.position.clone())
      if(meshScreenPosition.x >= startX && 
      meshScreenPosition.x <= endX &&
      meshScreenPosition.y >= startY &&
      meshScreenPosition.y <= endY) {
        return true
      }else {
        return false
      }
    }

    // 将一个三维坐标转化为屏幕坐标
    function xyz2Screen(position) {
      let vector = position.project(camera);
      let halfWidth = window.innerWidth / 2, halfHeight = window.innerHeight / 2; 
      return {
    　　x: Math.round(vector.x * halfWidth + halfWidth),
    　　y: Math.round(-vector.y * halfHeight + halfHeight)  
      }
    }

    function animate() {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
      controller.update(clock.getDelta());
    }

    function onResize() {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    }
  </script>
</html>
